#include "PassBallToBehaviour.h"

/*
 * Spravanie nahra loptu do daneho bodu s danou rychlostou
 *
 * @param	pos	bod, na ktory sa ma lopta kopnut
 * @param	speed rychlost prihravky
 */
void PassBallToBehaviour::Behave(const Point& pos, float speed)
{
	SKILLS_DBGN("%i: ->passing to position", world->state->GetSimTime());
	SKILLS_DBGN("%i: ->pos (%3.2f, %3.2f)", world->state->GetSimTime(), pos.GetX(), pos.GetY());

	Vector path = pos - world->ball->pos;

	float distance = path.GetLength();
	float realSpd = distance * (1 - world->params->server->ball_decay) + speed;
	
	if(realSpd > world->params->server->ball_speed_max)
	{
		realSpd = world->params->server->ball_speed_max;
	}

	Point target(world->ball->pos);
	if(distance > 0)
	{
		target = world->ball->pos + path * (realSpd / distance);
	}

	GetNearKickBehaviour()->Behave(target);
	GetTurnNeckToBehaviour()->Behave(target, world->me->pos + world->me->vel, 0);
}


/*
 * Nahra loptu hracovi. POZN.: Zase divna konstanta (.2f) vo funkcii.
 *
 * @param player hrac, ktoremu ideme prihravat
 * @param speed rychlost prihravky
 */
void PassBallToBehaviour::Behave(const Player& player, float speed /* = 0.7f */)
{
	SKILLS_DBGN("%i: ->passing to %s player %i", world->state->GetSimTime(), player.GetSide() == OUR ? "our" : (player.GetSide() == THEIR ? ">>their<<" : ">>unknown<<"), player.GetUniform());
	SKILLS_DBGN("%i: ->pos (%3.2f, %3.2f)", world->state->GetSimTime(), player.pos.GetX(), player.pos.GetY());
	
	// Ta X-ova pozicia sa mi nezda. Ak simuluje urcitu chybu, tak preco nesimuluje aj Y-ovej suradnici?
	this->Behave(Point(player.pos.GetX() + 
		(world->me->pos - player.pos).GetLength() * .2f, player.pos.GetY()), speed);
}


/*
 * Zadana rychlost sa prekalkuluje tak, aby bola podla vzorca brana do uvahy aj vzdialenost a natocenie hraca,
 * ked prihrava
 *
 * @param requirSpeed	pozadovana rychlost
 */
float PassBallToBehaviour::CorrectPassSpeed(float requirSpeed)
{	
	static float fEp, fDirDiff, fDistBball;
	fEp = world->params->server->maxpower * world->params->server->kick_power_rate;
	fDirDiff = ((world->ball->pos - world->me->pos) - world->me->GetAbsDir()).GetAngle().GetAbsDeg();
	fDistBball = (world->ball->pos - world->me->pos).GetLength() - 
		world->params->server->ball_size - world->params->server->player_size;
	fEp *= (1.f - (0.25f * fDirDiff / 180.f) - (0.25f * fDistBball / world->me->type->kickable_margin));

	return (requirSpeed / fEp) * requirSpeed;
}

/*
 * Brani super v nasej prihravke na urcite miesto?
 *
 * @param target	kam smeruje prihravka
 *
 * @return ci ten super brani alebo nie
 */
bool PassBallToBehaviour::IsBlockingEnemy(const Point& target)
{
	Vector diffTarget = target - world->me->pos;
	float distToTarget = diffTarget.GetLength();

	for(int e = 0; e < world->enemies.GetSize(); e++)
	{
		Vector diffEnemy = world->enemies[e].pos - world->me->pos;
		float fDistToEnemy = diffEnemy.GetLength();

	    if(fDistToEnemy < distToTarget && fDistToEnemy > 2)
		{
  			if((diffTarget.GetAngle() - diffEnemy.GetAngle()).GetAbsDeg() < 17)
			{
				return true;
			}
		}
	}
	
	return false;
}
